//
// Created by 11510 on 2024/7/15.
//

#ifndef DAY77_CALCULATOR2_CALCULATOR_H
#define DAY77_CALCULATOR2_CALCULATOR_H
#include <vector>
#include <stack>
#include <string>
#include <iostream>

enum NodeType {
    Operator,
    Operand
};
typedef struct _node {
    NodeType _type;
    std::string value;
} Node;

class Calculator {
private:
    std::vector<Node> postfix;
public:
    Calculator(std::vector<Node> &expression) : postfix(infix2Postfix(expression)) {}

    void print()const{
        for (auto elem: postfix) {
            printf("%s, ", elem.value.c_str());
        }
        puts("\n");
    }

    /**
     * 计算后缀表达式的值
     * @param postfix
     * @return
     */
    int evaluatePostfix() {
        std::stack<int> s;

        for (const auto &token: postfix) {
            if (token._type == Operand) {
                s.push(std::stoi(token.value));

            } else if (token._type == Operator) {
                int val2 = s.top();
                s.pop();
                int val1 = s.top();
                s.pop();
                if (token.value == "+") {
                    s.push(val1 + val2);
                } else if (token.value == "-") {
                    s.push(val1 - val2);
                } else if (token.value == "*") {
                    s.push(val1 * val2);
                } else if (token.value == "/") {
                    s.push(val1 / val2);
                }
            }
        }

        return s.top();
    }

    /**
     * 判断优先级
     * @param op
     * @return
     */
    int precedence(const std::string &op) {
        if (op == "+" || op == "-") {
            return 1;
        }

        if (op == "*" || op == "/") {
            return 2;
        }

        return 0;
    }

    /**
     * 中缀表达式转后缀表达式
     * @param infix
     * @return
     */
    std::vector<Node> infix2Postfix(const std::vector<Node> &infix) {
        std::vector<Node> postfix;
        std::stack<Node> s;

        for (const auto &token: infix) {
            if (token._type == Operand) {
                postfix.push_back(token);
            } else if (token._type == Operator) {
                while (!s.empty() && precedence(s.top().value) >= precedence(token.value)) {
                    postfix.push_back(s.top());
                    s.pop();
                }
                s.push(token);
            }
        }

        while (!s.empty()) {
            postfix.push_back(s.top());
            s.pop();
        }

        return postfix;
    }


    /**
     * 判断是操作数还是操作符
     * @param token
     * @return
     */
    bool isOperator(const std::string &token) const{
        return token == "+" || token == "-" || token == "*" || token == "/";
    }


};


#endif //DAY77_CALCULATOR2_CALCULATOR_H
